home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / x+opengl / glxdino.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  14.1 KB  |  380 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /* $Revision: 1.16 $ */
  18. /* compile: cc -o glxdino glxdino.c -lGLU -lGL -lX11 */
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <math.h>        /* for cos() and sin() */
  23. #include <GL/glx.h>        /* this includes the necessary X and gl.h headers */
  24. #include <GL/glu.h>        /* gluPerspective(), gluLookAt(), GLU polygon tesselator */
  25. #include <X11/Xatom.h>          /* for XA_RGB_DEFAULT_MAP atom */
  26. #include <X11/Xmu/StdCmap.h>    /* for XmuLookupStandardColormap() */
  27. #include <X11/extensions/shape.h>
  28.  
  29. typedef enum {
  30.     RESERVED, BODY_SIDE, BODY_EDGE, BODY_WHOLE, ARM_SIDE, ARM_EDGE, ARM_WHOLE,
  31.     LEG_SIDE, LEG_EDGE, LEG_WHOLE, EYE_SIDE, EYE_EDGE, EYE_WHOLE, DINOSAUR
  32. }               displayLists;
  33.  
  34. Display        *dpy;
  35. Window          win;
  36. GLfloat         angle = 30; /* in degrees */
  37. GLboolean       doubleBuffer = GL_TRUE, iconic = GL_FALSE, keepAspect = GL_FALSE, round = GL_FALSE;
  38. int             W = 300, H = 300;
  39. XSizeHints      sizeHints = {0};
  40. GLdouble        bodyWidth = 2.0;
  41. int             configuration[] = {GLX_DOUBLEBUFFER, GLX_RGBA, GLX_DEPTH_SIZE, 16, None};
  42. GLfloat         body[][2] = { {0, 3}, {1, 1}, {5, 1}, {8, 4}, {10, 4}, {11, 5}, {11, 11.5},
  43.         {13, 12}, {13, 13}, {10, 13.5}, {13, 14}, {13, 15}, {11, 16}, {8, 16}, {7, 15},
  44.         {7, 13}, {8, 12}, {7, 11}, {6, 6}, {4, 3}, {3, 2}, {1, 2}};
  45. GLfloat         arm[][2] = { {8, 10}, {9, 9}, {10, 9}, {13, 8}, {14, 9}, {16, 9}, {15, 9.5},
  46.         {16, 10}, {15, 10}, {15.5, 11}, {14.5, 10}, {14, 11}, {14, 10}, {13, 9}, {11, 11},
  47.         {9, 11}};
  48. GLfloat         leg[][2] = { {8, 6}, {8, 4}, {9, 3}, {9, 2}, {8, 1}, {8, 0.5}, {9, 0}, {12, 0},
  49.         {10, 1}, {10, 2}, {12, 4}, {11, 6}, {10, 7}, {9, 7}};
  50. GLfloat         eye[][2] = { {8.75, 15}, {9, 14.7}, {9.6, 14.7}, {10.1, 15}, {9.6, 15.25},
  51.         {9, 15.25}};
  52. GLfloat        lightZeroPosition[] = { -10.0, 4.0, -10.0, 1.0 };
  53. GLfloat        lightZeroColor[] = { 0.8, 1.0, 0.8, 1.0 };    /* green-tinted */
  54. GLfloat        lightOnePosition[] = { 1.0, -2.0, -1.0, 0.0 };
  55. GLfloat        lightOneColor[] = { 0.6, 0.3, 0.2, 1.0 };    /* red-tinted */
  56. GLfloat        skinColor[] = { 0.1, 1.0, 0.1, 1.0 }, eyeColor[] = { 1.0, 0.2, 0.2, 1.0 };
  57.  
  58. void
  59. fatalError(char *message)
  60. {
  61.     fprintf(stderr, "glxdino: %s\n", message);
  62.     exit(1);
  63. }
  64.  
  65. Colormap
  66. getColormap(XVisualInfo * vi)
  67. {
  68.     Status          status;
  69.     XStandardColormap *standardCmaps;
  70.     Colormap        cmap;
  71.     int             i, numCmaps;
  72.  
  73.     status = XmuLookupStandardColormap(dpy, vi->screen, vi->visualid,
  74.                vi->depth, XA_RGB_DEFAULT_MAP, /* replace */ False, /* retain */ True);
  75.     if (status == 1) {
  76.     status = XGetRGBColormaps(dpy, RootWindow(dpy, vi->screen),
  77.                  &standardCmaps, &numCmaps, XA_RGB_DEFAULT_MAP);
  78.     if (status == 1)
  79.         for (i = 0; i < numCmaps; i++)
  80.         if (standardCmaps[i].visualid == vi->visualid) {
  81.             cmap = standardCmaps[i].colormap;
  82.             XFree(standardCmaps);
  83.             return cmap;
  84.         }
  85.     }
  86.     /* be lazy; could try to make an unshared colormap, but too involved for this example */
  87.     if (vi->class != TrueColor) fatalError("no standard colormap found for non-TrueColor visual");
  88.     /* if no standard colormap but TrueColor, just make an unshared one */
  89.     cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen), vi->visual, AllocNone);
  90.     return cmap;
  91. }
  92.  
  93. void
  94. extrudeSolidFromPolygon(GLfloat data[][2], unsigned int dataSize, GLdouble thickness, GLuint side,
  95.                         GLuint edge, GLuint whole)
  96. {
  97.     static GLUtriangulatorObj *tobj = NULL;
  98.     GLdouble        vertex[3];
  99.     int             i;
  100.     int            count = dataSize / (2*sizeof(GLfloat));
  101.  
  102.     if (tobj == NULL) {
  103.     tobj = gluNewTess(); /* create and initialize a GLU polygon tesselation object */
  104.     gluTessCallback(tobj, GLU_BEGIN, glBegin);
  105.     gluTessCallback(tobj, GLU_VERTEX, glVertex2fv); /* semi-tricky */
  106.     gluTessCallback(tobj, GLU_END, glEnd);
  107.     }
  108.     glNewList(side, GL_COMPILE);
  109.     glShadeModel(GL_SMOOTH); /* smooth shade minimizes seeing tessellation */
  110.         gluBeginPolygon(tobj);
  111.             for (i = 0; i < count; i++) {
  112.             vertex[0] = data[i][0]; vertex[1] = data[i][1]; vertex[2] = 0;
  113.             gluTessVertex(tobj, vertex, &data[i]);
  114.             }
  115.         gluEndPolygon(tobj);
  116.     glEndList();
  117.     glNewList(edge, GL_COMPILE);
  118.     glShadeModel(GL_FLAT); /* flat shade keeps angular hands from being "smoothed" */
  119.         glBegin(GL_QUAD_STRIP);
  120.     for (i = 0; i <= count; i++) { /* mod function handles closing the edge */
  121.             glVertex3f(data[i % count][0], data[i % count][1], 0.0);
  122.             glVertex3f(data[i % count][0], data[i % count][1], thickness);
  123.         glNormal3f(data[(i+1) % count][1]-data[i % count][1], 
  124.             data[i % count][0]-data[(i+1) % count][0], 0.0); /* last normal is extraneous */
  125.     }
  126.         glEnd();
  127.     glEndList();
  128.     glNewList(whole, GL_COMPILE);
  129.         glFrontFace(GL_CW);
  130.         glCallList(edge);
  131.         glNormal3f(0.0, 0.0, -1.0); /* constant normal for side */
  132.         glCallList(side);
  133.         glPushMatrix();
  134.             glTranslatef(0.0, 0.0, thickness);
  135.             glFrontFace(GL_CCW);
  136.             glNormal3f(0.0, 0.0, 1.0); /* opposite constant normal for other side */
  137.             glCallList(side);
  138.         glPopMatrix();
  139.     glEndList();
  140. }
  141.  
  142. void
  143. makeDinosaur(void)
  144. {
  145.     GLfloat         bodyWidth = 3.0;
  146.  
  147.     extrudeSolidFromPolygon(body, sizeof(body), bodyWidth, BODY_SIDE, BODY_EDGE, BODY_WHOLE);
  148.     extrudeSolidFromPolygon(arm, sizeof(arm), bodyWidth / 4, ARM_SIDE, ARM_EDGE, ARM_WHOLE);
  149.     extrudeSolidFromPolygon(leg, sizeof(leg), bodyWidth / 2, LEG_SIDE, LEG_EDGE, LEG_WHOLE);
  150.     extrudeSolidFromPolygon(eye, sizeof(eye), bodyWidth + 0.2, EYE_SIDE, EYE_EDGE, EYE_WHOLE);
  151.     glNewList(DINOSAUR, GL_COMPILE);
  152.         glMaterialfv(GL_FRONT, GL_DIFFUSE, skinColor);
  153.         glCallList(BODY_WHOLE);
  154.         glPushMatrix();
  155.             glTranslatef(0.0, 0.0, bodyWidth);
  156.             glCallList(ARM_WHOLE);
  157.             glCallList(LEG_WHOLE);
  158.             glTranslatef(0.0, 0.0, -bodyWidth - bodyWidth / 4);
  159.             glCallList(ARM_WHOLE);
  160.             glTranslatef(0.0, 0.0, -bodyWidth / 4);
  161.             glCallList(LEG_WHOLE);
  162.             glTranslatef(0.0, 0.0, bodyWidth / 2 - 0.1);
  163.             glMaterialfv(GL_FRONT, GL_DIFFUSE, eyeColor);
  164.             glCallList(EYE_WHOLE);
  165.         glPopMatrix();
  166.     glEndList();
  167. }
  168.  
  169. void
  170. redraw(void)
  171. {
  172.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  173.     glCallList(DINOSAUR);
  174.     if (doubleBuffer) glXSwapBuffers(dpy, win);    /* buffer swap does implicit glFlush */
  175.         else glFlush();                /* explicit flush for single buffered case */
  176. }
  177.  
  178. /**** X Shape Extension related routines for round glxdino! ****/
  179.  
  180. Pixmap shapeMask;
  181. GC shapeGC;
  182. int pixWidth, pixHeight;
  183.  
  184. void
  185. initShaping(int w, int h)
  186. {
  187.    shapeMask = XCreatePixmap(dpy, win, w, h, 1);
  188.    shapeGC = XCreateGC(dpy, shapeMask, 0, NULL);
  189.    pixWidth = w;
  190.    pixHeight = h;
  191. }
  192.  
  193. void
  194. makeWindowRound(int w, int h)
  195. {
  196.     if(w != pixWidth || h != pixHeight) {
  197.        XFreePixmap(dpy, shapeMask);
  198.        shapeMask = XCreatePixmap(dpy, win, w, h, 1);
  199.        pixWidth = w;
  200.        pixHeight = h;
  201.     }
  202.     XSetForeground(dpy, shapeGC, 0);
  203.     XFillRectangle(dpy, shapeMask, shapeGC, 0, 0, w, h);
  204.     XSetForeground(dpy, shapeGC, 1);
  205.     XFillArc(dpy, shapeMask, shapeGC, 0, 0, w, h, 0, 360 * 64);
  206.     XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, shapeMask, ShapeSet);
  207.     XShapeCombineMask(dpy, win, ShapeClip, 0, 0, shapeMask, ShapeSet);
  208. }
  209.  
  210. void
  211. main(int argc, char **argv)
  212. {
  213.     XVisualInfo    *vi;
  214.     Colormap        cmap;
  215.     XSetWindowAttributes swa;
  216.     XWMHints       *wmHints;
  217.     Atom            wmDeleteWindow;
  218.     GLXContext      cx;
  219.     XEvent          event;
  220.     GLboolean       needRedraw = GL_FALSE, recalcModelView = GL_TRUE;
  221.     char           *display = NULL, *geometry = NULL;
  222.     int             flags, x, y, width, height, lastX, i, dummy;
  223.  
  224.     /*** (1) process normal X command line arguments ***/
  225.     for (i = 1; i < argc; i++) {
  226.     if (!strcmp(argv[i], "-geometry")) {
  227.         i++;
  228.         if (i >= argc) fatalError("follow -geometry option with geometry parameter");
  229.         geometry = argv[i];
  230.     } else if (!strcmp(argv[i], "-display")) {
  231.         i++;
  232.         if (i >= argc) fatalError("follow -display option with display parameter");
  233.         display = argv[i];
  234.     } else if (!strcmp(argv[i], "-iconic")) iconic = GL_TRUE;
  235.     else if (!strcmp(argv[i], "-keepaspect")) keepAspect = GL_TRUE;
  236.     else if (!strcmp(argv[i], "-single")) doubleBuffer = GL_FALSE;
  237.     else if (!strcmp(argv[i], "-round")) round = GL_TRUE;
  238.     else fatalError("bad option");
  239.     }
  240.  
  241.     /*** (2) open a connection to the X server ***/
  242.     dpy = XOpenDisplay(display);
  243.     if (dpy == NULL) fatalError("could not open display");
  244.  
  245.     /*** (3) make sure OpenGL's GLX extension supported ***/
  246.     if (!glXQueryExtension(dpy, NULL, NULL))
  247.     fatalError("X server has no OpenGL GLX extension");
  248.  
  249.     /*** (3.5) make sure Shape extension supported if round enabled ***/
  250.     if(round && !XShapeQueryExtension(dpy, &dummy, &dummy))
  251.     fatalError("X server has no shape extension");
  252.  
  253.     /*** (4) find an appropriate visual and a colormap for it ***/
  254.     /* find an OpenGL-capable RGB visual with depth buffer */
  255.     if(!doubleBuffer) goto SingleBufferOverride;
  256.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), configuration);
  257.     if (vi == NULL) {
  258.     SingleBufferOverride:
  259.     vi = glXChooseVisual(dpy, DefaultScreen(dpy), &configuration[1]);
  260.     if (vi == NULL) fatalError("no RGB visual with depth buffer");
  261.     doubleBuffer = GL_FALSE;
  262.     }
  263.     cmap = getColormap(vi);
  264.  
  265.     /*** (5) create an OpenGL rendering context  ***/
  266.     /* create an OpenGL rendering context */
  267.     cx = glXCreateContext(dpy, vi, /* no sharing of display lists */ NULL,
  268.                /* direct rendering if possible */ GL_TRUE);
  269.     if (cx == NULL) fatalError("could not create rendering context");
  270.  
  271.     /*** (6) create an X window with the selected visual and right properties ***/
  272.     flags = XParseGeometry(geometry, &x, &y, (unsigned int *) &width, (unsigned int *) &height);
  273.     if (WidthValue & flags) {
  274.     sizeHints.flags |= USSize;
  275.     sizeHints.width = width;
  276.     W = width;
  277.     }
  278.     if (HeightValue & flags) {
  279.     sizeHints.flags |= USSize;
  280.     sizeHints.height = height;
  281.     H = height;
  282.     }
  283.     if (XValue & flags) {
  284.     if (XNegative & flags) x = DisplayWidth(dpy, DefaultScreen(dpy)) + x - sizeHints.width;
  285.     sizeHints.flags |= USPosition;
  286.     sizeHints.x = x;
  287.     }
  288.     if (YValue & flags) {
  289.     if (YNegative & flags) y = DisplayHeight(dpy, DefaultScreen(dpy)) + y - sizeHints.height;
  290.     sizeHints.flags |= USPosition;
  291.     sizeHints.y = y;
  292.     }
  293.     if (keepAspect) {
  294.     sizeHints.flags |= PAspect;
  295.     sizeHints.min_aspect.x = sizeHints.max_aspect.x = W;
  296.     sizeHints.min_aspect.y = sizeHints.max_aspect.y = H;
  297.     }
  298.     swa.colormap = cmap;
  299.     swa.border_pixel = 0;
  300.     swa.event_mask = ExposureMask | ButtonPressMask | Button1MotionMask | StructureNotifyMask;
  301.     win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), sizeHints.x, sizeHints.y, W, H,
  302.                         0, vi->depth, InputOutput, vi->visual,
  303.             CWBorderPixel|CWColormap|CWEventMask, &swa);
  304.     XSetStandardProperties(dpy, win, "OpenGLosaurus", "glxdino", None, argv, argc, &sizeHints);
  305.     wmHints = XAllocWMHints();
  306.     wmHints->initial_state = iconic ? IconicState : NormalState;
  307.     wmHints->flags = StateHint;
  308.     XSetWMHints(dpy, win, wmHints);
  309.     wmDeleteWindow = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  310.     XSetWMProtocols(dpy, win, &wmDeleteWindow, 1);
  311.     if(round) {
  312.         initShaping(W, H);
  313.         makeWindowRound(W, H);
  314.     }
  315.  
  316.     /*** (7) bind the rendering context to the window ***/
  317.     glXMakeCurrent(dpy, win, cx);
  318.  
  319.     /*** (8) make the desired display lists ***/
  320.     makeDinosaur();
  321.  
  322.     /*** (9) configure the OpenGL context for rendering ***/
  323.     glEnable(GL_CULL_FACE);    /* ~50% better perfomance than non-face culled on Starter Indigo */
  324.     glEnable(GL_DEPTH_TEST);    /* enable depth buffering */
  325.     glEnable(GL_LIGHTING);    /* enable lighting */
  326.     glEnable(GL_NORMALIZE);    /* automatically scale normal vectors to unit vectors */
  327.     glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
  328.     glLightfv(GL_LIGHT0, GL_POSITION, lightZeroPosition);
  329.     glLightfv(GL_LIGHT0, GL_DIFFUSE, lightZeroColor);
  330.     glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, 0.1);
  331.     glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, 0.05);
  332.     glLightfv(GL_LIGHT1, GL_POSITION, lightOnePosition);
  333.     glLightfv(GL_LIGHT1, GL_DIFFUSE, lightOneColor);
  334.     glEnable(GL_LIGHT0); glEnable(GL_LIGHT1);    /* enable both lights */
  335.     glMatrixMode(GL_PROJECTION);        /* set up projection transform */
  336.     gluPerspective(40.0, 1, 1.0, 40.0);
  337.     gluLookAt(0.0, 0.0, -30.0, 0, 0, 0, 0, 1, 0);
  338.     glMatrixMode(GL_MODELVIEW);            /* now change to modelview */
  339.  
  340.     /*** (10) request the X window to be displayed on the screen ***/
  341.     XMapWindow(dpy, win);
  342.  
  343.     /*** (11) dispatch X events ***/
  344.     while (1) {
  345.     do {
  346.         XNextEvent(dpy, &event);
  347.         switch (event.type) {
  348.         case MotionNotify:
  349.         recalcModelView = GL_TRUE;
  350.         angle -= (lastX - event.xmotion.x);
  351.         case ButtonPress:
  352.         lastX = event.xbutton.x;
  353.         break;
  354.         case ConfigureNotify:
  355.         glViewport(0, 0, event.xconfigure.width, event.xconfigure.height);
  356.         if(round) makeWindowRound(event.xconfigure.width, event.xconfigure.height);
  357.         /* fall through... */
  358.         case Expose:
  359.         needRedraw = GL_TRUE;
  360.         break;
  361.         case ClientMessage:
  362.         if (event.xclient.data.l[0] == wmDeleteWindow) exit(0);
  363.         break;
  364.         }
  365.     } while (XPending(dpy));/* loop to compress events */
  366.     if (recalcModelView) {
  367.         /* reset modelview matrix to the identity matrix */
  368.         glLoadIdentity();
  369.             glRotatef(angle, 0.0, 1.0, 0.0);
  370.         glTranslatef(-8, -8, -bodyWidth / 2);
  371.         recalcModelView = GL_FALSE;
  372.         needRedraw = GL_TRUE;
  373.     }
  374.     if (needRedraw) {
  375.         redraw();
  376.         needRedraw = GL_FALSE;
  377.     }
  378.     }
  379. }
  380.